package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.DateUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.constants.RedisConstants;
import com.tianji.learning.entity.mq.SignInMessage;
import com.tianji.learning.entity.po.PointsRecord;
import com.tianji.learning.entity.vo.PointsStatisticsVO;
import com.tianji.learning.enums.PointsRecordType;
import com.tianji.learning.mapper.PointsRecordMapper;
import com.tianji.learning.service.IPointsRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 学习积分记录，每个月底清零 服务实现类
 * </p>
 *
 * @author lemon
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PointsRecordServiceImpl extends ServiceImpl<PointsRecordMapper, PointsRecord> implements IPointsRecordService {

    private final StringRedisTemplate stringRedisTemplate;

    /**
     * 添加积分消息-根据积分类型添加积分
     *
     * @param message
     * @param recordType
     */
    @Override
    public void addPointsRecord(SignInMessage message, PointsRecordType recordType) {
        Long userId = message.getUserId();

        // 最大上限
        int maxPoints = recordType.getMaxPoints();
        int realPoints = message.getPoints(); // 真实需要加的积分
        // 表示有积分上限的
        if (maxPoints > 0) {
            // 我们要先查询一下当前用户的积分
            // 根据这个type 和 userId 查询积分记录
            // 还有就是今天的范围
            LocalDateTime now = LocalDateTime.now();
            LocalDateTime dayStartTime = DateUtils.getDayStartTime(now);
            LocalDateTime dayEndTime = DateUtils.getDayEndTime(now);
            QueryWrapper<PointsRecord> recordQueryWrapper = new QueryWrapper<>();
            recordQueryWrapper.select("sum(points) as totalPoints");
            recordQueryWrapper.eq("user_id", userId);
            recordQueryWrapper.eq("type", recordType.getValue());
            recordQueryWrapper.between("create_time", dayStartTime, dayEndTime);

            Map<String, Object> map = this.getMap(recordQueryWrapper);
            int currentPoints = 0; // 当前的积分
            if (map != null) {
                BigDecimal totalPoints = (BigDecimal) map.get("totalPoints");
                currentPoints = totalPoints.intValue();
            }

            // 表示已经达到上限
            if (currentPoints >= maxPoints) {
                return;
            }

            // 本次实际应该增加多少分
            if (realPoints + currentPoints > maxPoints) {
                realPoints = maxPoints - currentPoints;
            }

        }
        // 保存积分记录
        PointsRecord pointsRecord = new PointsRecord();
        pointsRecord.setUserId(userId);
        pointsRecord.setType(recordType);
        pointsRecord.setPoints(realPoints);

        this.save(pointsRecord);

        // TODO 累加并保存总积分值
        LocalDateTime now = LocalDateTime.now();
        String format = now.format(DateTimeFormatter.ofPattern("yyyyMM"));
        String key = RedisConstants.POINTS_BOARD_KEY_PREFIX + format;

        // 保存到redis中
        stringRedisTemplate.opsForZSet().incrementScore(key, userId.toString(), realPoints);

    }

    /**
     * 查询今日获取积分情况
     *
     * @return
     */
    @Override
    public List<PointsStatisticsVO> queryMyPointsToday() {
        // 查询表
        // 根据type 返回每一个type的积分
        Long userId = UserContext.getUser();

        // 时间
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime dayStartTime = DateUtils.getDayStartTime(now);
        LocalDateTime dayEndTime = DateUtils.getDayEndTime(now);

        QueryWrapper<PointsRecord> recordQueryWrapper = new QueryWrapper<>();
        recordQueryWrapper.select("type", "sum(points) as points");
        recordQueryWrapper.eq("user_id", userId);
        recordQueryWrapper.between("create_time", dayStartTime, dayEndTime);
        recordQueryWrapper.groupBy("type");

        List<PointsRecord> list = this.list(recordQueryWrapper);
        if (CollUtils.isEmpty(list)) {
            return CollUtils.emptyList();
        }
        List<PointsStatisticsVO> voList = CollUtils.newArrayList();
        // 封装成VO
        for (PointsRecord pointsRecord : list) {
            PointsStatisticsVO vo = new PointsStatisticsVO();
            vo.setType(pointsRecord.getType().getDesc()); // 积分类型名称
            vo.setMaxPoints(pointsRecord.getType().getMaxPoints()); // 积分上限
            vo.setPoints(pointsRecord.getPoints()); // 积分总的获得

            voList.add(vo);
        }
        return voList;
    }
}
